﻿using mozhi.smarterp.BasicData.DataLinkages.Events;
using mozhi.smarterp.BasicData.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp;

namespace mozhi.smarterp.BasicData.Products
{
    public class Product : AggregateRootBase
    {
        public ProductType Type { get; private set; }

        public Guid? ImageId { get; private set; }

        public string BarCode { get; private set; }

        public bool Saleable { get; private set; }

        public bool Purchasable { get; private set; }

        /// <summary>
        /// 可生产的
        /// </summary>
        public bool Producible { get; private set; }

        public bool Outsourceable { get; private set; }

        public bool Assetable {  get; private set; }

        /// <summary>
        /// 基本单位
        /// </summary>
        public Guid BasicUnitId { get; private set; }

        /// <summary>
        /// 规格型号
        /// </summary>
        public string Model‌ { get; private set; }

        public Guid? DefaultTaxRateId { get; set; }

        public Guid? DefaultSupplierId { get; set; }


        private Product()
        {

        }

        public Product(Guid id, string code, string name, ProductType type, string barcode , Guid basicUnitId , Guid? defaultTaxRateId, Guid? defaultSupplierId,string model , bool activate) : base(id, code, name, activate)
        {
            Type = type;

            BasicUnitId = basicUnitId;

            AddDistributedEvent(GetBasicDataLinkageEvent(basicUnitId , "Unit"));

            DefaultTaxRateId = defaultTaxRateId;

            if(defaultTaxRateId.HasValue)
                AddDistributedEvent(GetBasicDataLinkageEvent(defaultTaxRateId.Value, "TaxRate"));

            DefaultSupplierId = defaultSupplierId;

            if (defaultSupplierId.HasValue)
                AddDistributedEvent(GetBasicDataLinkageEvent(defaultSupplierId.Value, "Supplier"));

            Model = model;

            BarCode = barcode;

            Validate();
        }

        public void Change(string code, string name, ProductType type, string barcode , Guid basicUnitId, Guid? defaultTaxRateId, Guid? defaultSupplierId, string model, bool activated)
        {
            Type = type;

            var unitEqual = basicUnitId == BasicUnitId;

            if (!unitEqual)
            {
                AddDistributedEvent(GetBasicDataLinkageDeleteEvent(BasicUnitId));
                AddDistributedEvent(GetBasicDataLinkageEvent(basicUnitId, "Unit"));
            }

            BasicUnitId = basicUnitId;

            var taxRateEqual = defaultTaxRateId == DefaultTaxRateId;

            if (!taxRateEqual)
            {
                if (DefaultTaxRateId.HasValue)
                    AddDistributedEvent(GetBasicDataLinkageDeleteEvent(DefaultTaxRateId.Value));

                if (defaultTaxRateId.HasValue)
                    AddDistributedEvent(GetBasicDataLinkageEvent(defaultTaxRateId.Value, "TaxRate"));
            }

            DefaultTaxRateId = defaultTaxRateId;

            var supplierEqual = DefaultSupplierId == defaultSupplierId;

            if (!supplierEqual)
            {
                if (DefaultSupplierId.HasValue)
                    AddDistributedEvent(GetBasicDataLinkageDeleteEvent(DefaultSupplierId.Value));

                if (defaultSupplierId.HasValue)
                    AddDistributedEvent(GetBasicDataLinkageEvent(defaultSupplierId.Value, "Supplier"));
            }


            DefaultSupplierId = defaultSupplierId;
            Model = model;

            BarCode = barcode;

            base.Change(code, name, activated);
        }

        public void ChangeRestraint(bool saleable , bool purchasable , bool producible , bool outsourceable , bool assetable)
        {
            Saleable = saleable;
            Purchasable = purchasable;
            Producible = producible;
            Outsourceable = outsourceable;
            Assetable = assetable;

            //可资产，不允许销售，采购和委外
            if (Assetable)
            {
                if (Saleable)
                    throw new UserFriendlyException("资产不允许销售","100000");

                if (Producible)
                    throw new UserFriendlyException("资产不允许生产", "100000");

                if (Outsourceable)
                    throw new UserFriendlyException("资产不允许委外", "100000");
            }
        }

        public void ChangeImage(Guid? imageId)
        {
            ImageId = imageId;
        }


        #region
        protected override void Validate()
        {
            base.Validate();
            if (BasicUnitId == default)
                throw new ArgumentNullException(nameof(BasicUnitId));

            if (Type == default)
                throw new ArgumentNullException(nameof(Type));
        }

        private BasicDataLinkageCreateEvent GetBasicDataLinkageEvent(Guid providerId, string providerType)
        {
            return new BasicDataLinkageCreateEvent(TenantId, providerId, providerType, null, Id, nameof(Product), $"{Code}-{Name}");
        }

        private BasicDataDataLinkageDeleteEvent GetBasicDataLinkageDeleteEvent(Guid providerId)
        {
            return new BasicDataDataLinkageDeleteEvent(TenantId, providerId, Id);
        }
        
        #endregion
    }
}
